{literal}
<h2>Introduction</h2>

Validators are very useful for validating data from forms.<br>
DomArObject never allowes bad values for properties. If bad value is given, then validation error is raised and saving object is not allowed.<br>
If bad value is given it won't be stored as object property value!<br>
For example
<pre class="code">
&lt;?php
class MyClass extends DomArObject {
	/**
	* @orm text
	*/
	public $myText = 'Default text';
}
$a  = new MyClass();
$a-&gt;myText = 10; // Int is not allowed for text type.
echo $a-&gt;myText; // prints 'Default text'
echo $a-&gt;getLastValidationMessage(); // prints something like "1) Bad value for MyClass property myText (int)10
?&gt;
</pre>




<h2>Custom validator methods</h2>

Very cool way to write validators for you datamodel object is this:
<pre class="code">
&lt;?php
/**
* @orm tableName myusers
*/ 
class MyUser extends DomArObject {
	/**
	* @orm char(20)
	*/
	public $username;
	/**
	* @orm char(30)
	* @orm validator method myValidator
	*/
	public $nickname;
	
	public function myValidator( $value ) {
		if( $value == 'Admin' or $value == 'Moderator')
			return 1001;
		return 0;
	}
	
	public function getValidationErrorMessages() {
		return array(
			'nickname' =&gt; array(
				1001 =&gt; 'You nickname is not allowed. Please choose new nickname!',
			),
		);
	}
}

// and using it:
$user = new MyUser();
$user->nickname = 'Admin';
if( $user->save() ) {
	echo 'Cool, user saved!';
} else {
	// error happened. Lets get last message.
	echo $user->getLastValidationMessage();
}


?&gt;
</pre>

<h2>Custom validator methods basic syntax </h2>
<pre class="code">
&lt;?php
class MyUser extends DomArObject {
	/**
	* @orm char(30)
	* @orm validator method myValidator(ARG1,ARG2)
	*/
	public $nickname;
	
	/**
	* @param Mixed Value to be validated
	* @param Mixed Argument 1 that was defined in @orm clause.
	* @param Mixed Argument 2 that was defined in @orm clause.
	* @param Array $customParams This argument is used to create dynamic validation messages. See Dynamic validator messages section.
	*/	
	public function myValidator( $value, $ARG1, $ARG2, &$customParams ) {
		// some validation
	}
}
?&gt;
</pre>



<h2>Dynamic validator messages</h2>

Sometimes you might need dynamic messages. For example "Number $someNumber is too small1". With static messages it is not  possible, but with dynamic it is. 
Setting up dynamic message is very easy. See sample code below.
<pre class="code">
&lt;?php
/**
* @orm tableName myusers
*/ 
class MyClass extends DomArObject {
	/**
	* @orm int(10)
	* @orm validator method myValidator
	*/
	public $someNumber
	
	public function myValidator( $value, &$customMessageParams ) {
		
		$minValue = 50;
		if( $value <= $minValue ) {
			&$customMessageParams['nr'] = (int)$value;
			&$customMessageParams['minValue'] = $minValue
			return 1001;
		}
		
		if( $value%2 != 0 ) {
			&$customMessageParams['nr'] = (int)$value;
			&$customMessageParams['mod'] = (int)$value%2;
			return 1002;
		}
		return 0;
	}
	
	public function getValidationErrorMessages() {
		return array(
			'someNumber' =&gt; array(
				1001 =&gt; 'Given number [$nr] is smaller than [$minValue]! Please choose bigger number!',
				1002 =&gt; 'Given number [$nr] do not paired. It leaves mod [$mod]! Please choose paired number!',
			),
		);
	}
}

// and using it:
$user = new MyClass();
$user->someNumber = 49;
if( !$user->save() ) {
	echo implode('<br>', $user->getValidationMessages() );
	// prints error texts for error 1001 and 1002
}


?&gt;
</pre>

<h2>Reusable validators </h2>

Sometimes you might want to write reusable validators. For our example we will user "greater than" validator. 
This is validator you don't want to write into every method, you want it to be easier!
<pre class="code">
&lt;?php
class DomArValidator_Ge extends DomArValidator {
	
	private $value;
	
	public function __construct( $value ) {
		 $this->value = (int)$value;
	}
	
	public function validate( $value ) {
		return $value >= $this->value;
	}
}
?&gt;
</pre>
And using it
<pre class="code">
&lt;?php
class Number extends DomArObject {
	/**
	* @orm int(2)
	*  Number must be greater or equal to 10
 	* @orm validator ge(10)
	*/
	public $number;
}
?&gt;
</pre>


<h2>Validators and Relationships</h2>
If you have relationships then all objects that should be saved must validate!<br>
<pre class="code">
&lt;?php
class Article extends DomArObject {
	/**
	* @orm text
	*/
	public $title;
	/**
	* @orm has parent Category inverse articles
	*/
	public $category;
	
	public function getValidationErrorMessages() {
		return array(
			'title' =&gt; array(
				1 =&gt; 'Article title must be string!',
			),
		);
	}
}
?&gt;
</pre>

<pre class="code">
&lt;?php
class Category extends DomArObject {
	/**
	* @orm text
	*/
	public $name;
	/**
	* @orm has children Article inverse category
	*/
	public $articles;
}
?&gt;
</pre>

And now testing validation
<pre class="code">
&lt;?php
// Creating article object
$article = new Article();
$article->title = 10; // Ooops! Bad value;

// Creating category object
$cat = new Category();
$cat-&gt;name = 'Fashion news';
$cat->articles[] = $article;

// trying to save category and article, but it will fail, as (int)10 is not correct value for Article title
if( !$cat->save() ) {
	echo $cat->getLastValidationMessage(); // Prints error "Article title must be string!"
	// None of the objects will be saved!
}
?&gt;
</pre>


<h2>Relationship calling validators </h2>
If you have for example 1:N relationship and both sides validate child/parent object then both validators will be always called. See sample below:<br>
Notice, that validaton error messages are defined twice!
<pre class="code">
&lt;?php
class Article extends DomArObject {
	/**
	* @orm text
	*/
	public $title;
	/**
	* @orm has parent Category inverse article categoryValidator()
	*/
	public $category;
	
	public function categoryValidator( Category $category ) {
		if( strstr($category, 'Boring') > 0 ) {
			return 1002;
		}
		return 0;
	}
	
	public function getValidationErrorMessages() {
		return array(
			'category' =&gt; array(
				1001 =&gt; 'Added category can not containt articles which title contains word Hello!',
				1002 =&gt; 'Article does not allow category which name contains word Boring',
			),
		);
	}
}

class Category extends DomArObject {
	/**
	* @orm text
	*/
	public $name;
	/**
	* @orm has children Article inverse category
	* @orm validator method articleValidator
	*/
	public $articles;
	
	public function articleValidator( Article $article ) {
		if( strstr($article->title, 'Hello') > 0 )
			return 1001;
		return 0;
	}
	
	public function getValidationErrorMessages() {
		return array(
			'articles' =&gt; array(
				1001 =&gt; 'You can not add article which title contains word Hello',
				1002 =&gt; 'Added article do not allow category which name contains word Boring',
			),
		);
	}
}
?&gt;
</pre>


{/literal}